#pragma once

#include <compl.h>

/* non-linearzable wait-free */
typedef struct mpsc_list{
	struct mpsc_list *next;
}mpsc_list_t;

SAI void mpsc_list_init(mpsc_list_t *l){
	l->next = l;
}

/* push 头部 */
SAI mpsc_list_t *mpsc_list_push_head(mpsc_list_t *l, mpsc_list_t *nd){
	nd->next = l;
	// 必须rel
	mpsc_list_t *cur_head = swp(&l->next, nd);
	atm_strel(&nd->next, cur_head);
	return cur_head;
}

// 无锁
SAI mpsc_list_t *mpsc_list_pop_head(mpsc_list_t *l){
	mpsc_list_t *head = l;
	mpsc_list_t *next = head->next;
	if (next == l) {
		return (mpsc_list_t *)NULL;
	}
	l->next = next;
	atm_st(&l->next, next);
	mp_rmb(); /* 确保读到的节点已经写入 */
	return head;
}

typedef struct mpsc_dlist{
	struct mpsc_dlist *prev;
	struct mpsc_dlist *next;
}mpsc_dlist_t;

SAI void mpsc_dlist_init(mpsc_dlist_t *l){
	l->prev = l;
	l->next = l;
}


/* push 尾部(交换tail) */
/* push 头部 */
SAI mpsc_dlist_t *mpsc_dlist_push_tail(mpsc_dlist_t *l, mpsc_dlist_t *nd){
	nd->next = l;
	// 必须rel
	mpsc_dlist_t *prev = swp(&l->prev, nd);
	atm_strel(&prev->next, nd);
	return prev;
}

/* push 头部 */
SAI mpsc_dlist_t *mpsc_dlist_push_head(mpsc_dlist_t *l, mpsc_dlist_t *nd){
	nd->next = l;
	// 必须rel
	mpsc_dlist_t *cur_head = swp(&l->next, nd);
	atm_strel(&nd->next, cur_head);
	return nd;
}

SAI mpsc_dlist_t *mpsc_dlist_pop_head(mpsc_dlist_t *l, mpsc_dlist_t *nd){
	mpsc_dlist_t *head = l;
	mpsc_dlist_t *next = head->next;
	if (next == l) {
		return (mpsc_dlist_t *)NULL;
	}
	l->next = next;
	atm_st(&l->next, next);
	mp_rmb(); /* 确保读到的节点已经写入 */
	return head;
}
